﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using TinyROS.Messages;
using TinyROS.Exceptions;

namespace TinyROS
{
    public partial class SystemCore : IConsoleInteractive
    {
        private bool Exit = false;
        private Dictionary<string, Node> Nodes = new();
        private Dictionary<string, Topic> Topics = new();
        public SystemCore()
        {
            this.LoadedAsm = new();
            this.LoadedAsm.Add((Assembly.GetExecutingAssembly(), "TinyROS"));
        }
        public void Spin()
        {
            this.Exit = false;
            try
            {
                while (!this.Exit)
                {

                }               
            }
            catch
            {
                
            }
        }
        private void KeyBoardInterruptHandler(object sender, ConsoleCancelEventArgs args)
        {
            if(!this.Exit)
            {
                this.Exit = true;
                args.Cancel = true;
            }
            
        }
        public void RegisterNode(string name, Node node, bool raiseError = false)
        {
            try
            {
                if(this.Nodes.ContainsKey(name))
                {
                    throw new AlreadyExistException();
                }
                node.Init(this);
                this.Nodes.Add(name, node);
            }
            catch (AlreadyExistException)
            {
                if (raiseError) { throw; }
            }
            catch (NodeInitFailedExcepiton)
            {
                if (raiseError) { throw; }
            }
            catch
            {
                if (raiseError) { throw new NodeInitFailedExcepiton(); }
            }
        }
        public void RunNode(string nodeName)
        {
            var node = this.Nodes[nodeName];
            node.Run();
        }
        public void StopNode(string nodeName)
        {
            var node = this.Nodes[nodeName];
            node.Stop();
        }
        [Obsolete]
        public void RegisterTopic(Topic topic)
        {
            this.RegisterTopic(topic.Name, topic);
        }
        public void RegisterTopic(string name, Topic topic) 
        {
            if(!this.Topics.ContainsKey(name))
            {
                this.Topics.Add(name, topic);
            }
            else
            {
                throw new Exception("Topic already exists");
            }
        }
        public Topic GetTopic(string name)
        {
            if(this.Topics.ContainsKey(name))
            {
                return this.Topics[name];
            }
            else
            {
                return null;
            }
        }
        public TTopic RequestTopic<TTopic>(string name) where TTopic : Topic, new()
        {
            if(this.Topics.ContainsKey(name))
            {
                var topic = this.Topics[name] as TTopic;
                if(topic == null)
                {
                    throw new MessageTypeException();
                }
                else
                {
                    return topic;
                }               
            }
            else
            {
                var newTopic = new TTopic();
                this.Topics.Add(name, newTopic);
                return newTopic;
            }
        }
        public void ShutDown()
        {
            throw new NotImplementedException();
        }

        
        
    }

    public interface IConsoleInteractive
    {
        public abstract void Execute(string command);

    }

    
}
